/*
 * Copyright 2011 Vlad Goldman.  All rights reserved.
  
   This file is part of GooOutSync - Google Outlook Sync application
  
    Project page: http://goooutsync.googlecode.com

    GooOutSync is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    GooOutSync is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GooOutSync.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.vgold.goooutsync;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.log4j.Logger;

import com.google.gdata.util.common.util.Base64;
import com.google.gdata.util.common.util.Base64DecoderException;

public class GoogleCredentials {
	private String credentialsFile = "goooutsync.keystore";
	private GooOutSyncPreferences preferences;
	private Logger logger;
	private String user;
	private String password;
	private SecretKey key;
	private static GoogleCredentials ref;

	private GoogleCredentials() throws GooOutSyncException {
		logger = Logger.getLogger(GoogleCredentials.class);
		preferences = GooOutSyncPreferences.getGooOutSyncPreferences();
		loadCredentials();
	}

	public static GoogleCredentials getGoogleCredentials()
			throws GooOutSyncException {
		if (ref == null)
			ref = new GoogleCredentials();
		return ref;
	}

	/**
	 * @return the user
	 */
	public String getUser() {
		return user;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	public void setCredentials(String user, String password)
			throws GooOutSyncException {
		this.user = user;
		this.password = password;
		saveCredentials();
	}

	private void loadCredentials() throws GooOutSyncException {
		try {
			DESKeySpec keySpec = new DESKeySpec(
					"DhFm729IwpP238MbvYfj732".getBytes("UTF8"));
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			key = keyFactory.generateSecret(keySpec);
			user = preferences
					.getPreference(GooOutSyncPreferences.Prefs.google_username);
			String encryptedPwd = preferences
					.getPreference(GooOutSyncPreferences.Prefs.google_password);
			//logger.info("Loaded encrypted password:" + encryptedPwd);
			byte[] encrypedPwdBytes = Base64.decode(encryptedPwd);
			Cipher cipher = Cipher.getInstance("DES");// cipher is not thread
														// safe
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] plainTextPwdBytes = (cipher.doFinal(encrypedPwdBytes));
			password = new String(plainTextPwdBytes, "UTF8");
			logger.info("Decrypted encrypted password to:" + password);

		} catch (IOException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (Base64DecoderException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (BadPaddingException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		}

	}

	public void loadCredentialsFromFile() throws GooOutSyncException {
		try {
			DESKeySpec keySpec = new DESKeySpec(
					"Your secret Key phrase".getBytes("UTF8"));
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			key = keyFactory.generateSecret(keySpec);
			String line;
			BufferedReader input = new BufferedReader(new FileReader(
					credentialsFile));
			user = input.readLine();
			String encryptedPwd = input.readLine();
			byte[] encrypedPwdBytes = Base64.decode(encryptedPwd);
			Cipher cipher = Cipher.getInstance("DES");// cipher is not thread
														// safe
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] plainTextPwdBytes = (cipher.doFinal(encrypedPwdBytes));
			password = new String(plainTextPwdBytes, "UTF8");
			input.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			throw new GooOutSyncException(e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Base64DecoderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void saveCredentials() throws GooOutSyncException {
		try {
			DESKeySpec keySpec = new DESKeySpec(
					"DhFm729IwpP238MbvYfj732".getBytes("UTF8"));
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			key = keyFactory.generateSecret(keySpec);
			byte[] cleartext = password.getBytes("UTF8");
			logger.info("Saving password:" + password);
			Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread
														// safe
			cipher.init(Cipher.ENCRYPT_MODE, key);
			String encrypedPwd = Base64.encode(cipher.doFinal(cleartext));
			preferences.setPreference(
					GooOutSyncPreferences.Prefs.google_username, user);
			preferences.setPreference(
					GooOutSyncPreferences.Prefs.google_password, encrypedPwd);
		} catch (IOException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		} catch (BadPaddingException e) {
			e.printStackTrace();
			throw new GooOutSyncException(e);
		}

	}

	public void saveCredentialsToFile() {
		try {
			DESKeySpec keySpec = new DESKeySpec(
					"Your secret Key phrase".getBytes("UTF8"));
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			key = keyFactory.generateSecret(keySpec);
			byte[] cleartext = password.getBytes("UTF8");

			Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread
														// safe
			cipher.init(Cipher.ENCRYPT_MODE, key);
			String encrypedPwd = Base64.encode(cipher.doFinal(cleartext));
			BufferedWriter in = new BufferedWriter(new FileWriter(
					credentialsFile));
			in.write(user);
			in.newLine();
			in.write(encrypedPwd);
			in.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}
